#include "torrent_control.h"
#include "backup_server_connection.h"
#include <ncurses.h>

#include <boost/bind.hpp>
#include <iostream>



void on_piece_downloaded(torrent_control* torrent_controller, int piece_index)
{
    progress_info progress = torrent_controller->get_progress();
    libtorrent::bitfield pieces = progress.downloaded;

    int color = 0; //Normal, white on black.

    move(7,0); //Hardcoded to be below downloadinfo.
    attron(COLOR_PAIR(0));
    printw("---");
    attroff(COLOR_PAIR(0));
    for(int i = 0; i < torrent_controller->num_pieces(); ++i) {
        color = 0;
        attron(COLOR_PAIR(0));
        if(i%10 == 0) {
            if(i%100 == 0) {
                printw("\n");
            } else {
                printw(" ");
            }
        }
        attroff(COLOR_PAIR(0));
        //std::cerr << progress.piece_src[i] << std::endl;
        if(pieces[i] == 0) { //not downloaded yet.
            for(std::vector<libtorrent::partial_piece_info>::iterator it = progress.piece_states.begin(); it != progress.piece_states.end(); ++it) { 
                if(it->piece_index == i) { //If piece are in dl-queue.
                    color = it->piece_state + 3; // +3 due to ncurses.
                    break;
                } else { //Not found i dl-queue.
                    color = 0;
                }
            }
        } else { //if downloaded.
            color = progress.piece_src[i] + 1; // +1 due to ncurses.
        }
        if(torrent_controller->is_seed()) {
            color = progress.piece_src[i] + 1; // +1 due to ncurses.
        }
        //std::cerr << (pieces[i] == 0 ? '-' : '#');
        attron(COLOR_PAIR(color));
        printw("%i", progress.priorities[i]);
        attroff(COLOR_PAIR(color));
    }
    attron(COLOR_PAIR(0));
    printw("\n---");
    attroff(COLOR_PAIR(0));
    refresh();
//    std::cout << std::endl;
}

void print_torrent_info(torrent_control& torrent_controller) {
    download_info dl_info = torrent_controller.get_download_info();

    int color = 0;
    attron(COLOR_PAIR(color));
    move(0,0);
    printw("\nAntal Peers: %i", dl_info.num_peers);
    printw("\nAntal unchoked: %i", dl_info.num_unchoked);
    printw("\nAntal connections: %i", dl_info.num_connections);
    printw("\ncurrent dl rate(kb): %f", dl_info.download_rate/1024);
    printw("\ncurrent ul rate(kb): %f", dl_info.upload_rate/1024);
    printw("\nTotal downloaded(byte): %i", dl_info.total_download);
    printw("\n\n");
    attroff(COLOR_PAIR(color));
    refresh();
}

int main(int argc, char* argv[])
{   
    //ncurses.
    initscr(); //Init screen.
    start_color();
    init_pair(0, COLOR_BLACK, COLOR_BLACK); //Normal.
    init_pair(1, COLOR_GREEN, COLOR_BLACK); //torrent.
    init_pair(2, COLOR_CYAN, COLOR_BLACK); //backup.
    init_pair(3, COLOR_YELLOW, COLOR_BLACK); //multicast.
    init_pair(6, COLOR_WHITE, COLOR_GREEN); //Slow dl.
    init_pair(5, COLOR_BLACK, COLOR_RED); //Medium dl.
    init_pair(4, COLOR_BLACK, COLOR_RED); //Fast dl.


    torrent_control torrent_controller(std::string(argv[1]),
                                       "./",
                                       std::make_pair(6881,6889),
                                       true,
                                       "cowboycoders.se",
                                       "22234",
                                       "big_buck_bunny",
                                       3);

    
    torrent_controller.set_piece_finished_callback(
        boost::bind(on_piece_downloaded, &torrent_controller, _1));

    {
        if (argc != 2)
        {
            std::cerr << "usage: ./torrent_control_test torrent-file" << std::endl;
            sleep(1);
            return 1;
        }
        

        for(int i = 0; i < 1000; i += 10) {
            torrent_controller.add_pieces_from_backup_server(i, 10);
            usleep(100000);
        }

        while(true) { //FIXME
            print_torrent_info(torrent_controller);
            sleep(1);
        }

        std::string input;
        std::getline(std::cin, input);
        
        int bytes_read =  0;
        int bytes_to_read = 64*1024;
        int offset = 0;
        char * buffer = new char[bytes_to_read];
        
        bytes_read = torrent_controller.read_data(offset,bytes_to_read,buffer);

        //std::cerr << "Byte(s) read: " << bytes_read << " at offset: " << offset <<  std::endl;

        delete[] buffer;

    }
    
    endwin(); //End ncurses.

    return 0;
}
